﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.Text.RegularExpressions;

namespace ABII.AdminPanel
{
    public partial class AdminPanelForm : Form
    {
        public ConnectionState State { get; private set; }
        
        public AdminPanelForm()
        {
            InitializeComponent();
        }

        protected override CreateParams CreateParams {
            get {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;
                return cp;
            }
        }

        private void AdminPanelForm_Load(object sender, EventArgs e)
        {
            State = ConnectionState.NONE;
            ChangeState(State);
            tbLoginServer.Text = Properties.Settings.Default.Server;
            tbLoginUsername.Text = Properties.Settings.Default.Username;
            tbLoginPassword.Text = Properties.Settings.Default.Password;
            udLoginTimeout.Text = Properties.Settings.Default.Timeout.ToString();
            chkbLoginRemember.Checked = Properties.Settings.Default.Remember;
            //MessageBox.Show(tbLoginServer.Text + " " + tbLoginUsername.Text + " " + tbLoginPassword.Text);
            Connect();
        }

        private void btLoginConnect_Click(object sender, EventArgs e)
        {
            Connect();
        }

        private void miConnect_Click(object sender, EventArgs e)
        {
            if (miConnect.Text.Equals("Connect"))
            {
                Connect();
            }
            else
            {
                Disconnect();
            }
        }

        private void miExit_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void AdminPanelForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            return;
            if (State != ConnectionState.NONE)
            {
                DialogResult result = MessageBox.Show("Are you sure you want to exit the application?" + Environment.NewLine + 
                                                        "Any unsaved data will be lost!",
                                                        "Warning", 
                                                        MessageBoxButtons.YesNo, 
                                                        MessageBoxIcon.Warning, 
                                                        MessageBoxDefaultButton.Button2);
                e.Cancel = result == DialogResult.No;
                if (!e.Cancel)
                {
                    Database.Dispose();
                }
            }
        }

        private void tbProcessFilter_TextChanged(object sender, EventArgs e)
        {
            String pattern = tbProcessFilter.Text;
            Regex validator = new Regex(pattern, RegexOptions.IgnoreCase);
            List<Record> users = new List<Record>(Database.Users);
            Int32 index = 0;
            while (index < users.Count)
            {
                if (!validator.IsMatch(users[index].Name))
                {
                    users.RemoveAt(index);
                }
                else
                {
                    ++index;
                }
            }
            UserlistFill(lvProcessUsers, users, Database.Ranks);
        }

        private void lvProcessUsers_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lvProcessUsers.SelectedItems.Count > 0)
            {
                SelectUser(lvProcessUsers.SelectedItems[0].Text);
            }
        }

        private void btPrivateAdd_Click(object sender, EventArgs e)
        {

        }

        private void btPrivateRemove_Click(object sender, EventArgs e)
        {

        }

        private void btSave_Click(object sender, EventArgs e)
        {
            if (lvProcessUsers.SelectedItems.Count > 0)
            {
                SaveTab(lvProcessUsers.SelectedItems[0].Text);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Title = "Save ban list";
            sfd.Filter = "XML Database|*.xml";
            sfd.InitialDirectory = @"C:\Users\Csiszer\Desktop";

            if (sfd.ShowDialog() == DialogResult.OK)
            {
                Database.Export(sfd.FileName);
            }
        }

        private void feedbackButton_Click(object sender, EventArgs e)
        {
            Queries.GetFeedback();
        }

        private void blacklistAddButton_Click(object sender, EventArgs e)
        {
            Queries.AddBlackList(ipTextBox.Text, reasonTextBox.Text);
            MessageBox.Show("IP adress succesfully blacklisted.");
            ipTextBox.Text = ""; reasonTextBox.Text = "";
        }

        private void blacklistRemoveButton_Click(object sender, EventArgs e)
        {
            Queries.RemoveBlackList(ipTextBox.Text);
            MessageBox.Show("IP adress succesfully removed from blacklist.");
            ipTextBox.Text = ""; reasonTextBox.Text = "";
        }

        private void tcProcessProperties_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lvProcessUsers.SelectedItems.Count > 0)
            {
                SelectUser(lvProcessUsers.SelectedItems[0].Text);
            }
        }

        private void Connect()
        {
            try
            {
                ChangeState(ConnectionState.AUTH);
                if (chkbLoginRemember.Checked)
                {
                    Properties.Settings.Default.Server = tbLoginServer.Text;
                    Properties.Settings.Default.Username = tbLoginUsername.Text;
                    Properties.Settings.Default.Password = tbLoginPassword.Text;
                    Properties.Settings.Default.Timeout = Convert.ToInt32(udLoginTimeout.Text);
                }
                Properties.Settings.Default.Remember = chkbLoginRemember.Checked;
                Properties.Settings.Default.Save();

                Database.Authenticate(tbLoginUsername.Text, tbLoginPassword.Text);

                Database.GetPublicData();

                ComboBoxFill(cbProcessRanks, Database.Ranks);
                ComboBoxFill(cbProcessGenders, Database.Genders);
                UserlistFill(lvProcessUsers, Database.Users, Database.Ranks);

                ChangeState(ConnectionState.DONE);

            }
            catch(AuthenticationException ex)
            {
                Disconnect();
                MessageBox.Show(ex.ToString());
            }
        }

        private void ComboBoxFill(ComboBox control, List<Record> records)
        {
            control.BeginUpdate();
            control.Items.Clear();
            foreach (Record record in records)
            {
                control.Items.Add(record.Name);
            }
            if (control.Items.Count > 0)
            {
                control.SelectedIndex = 0;
            }
            control.EndUpdate();
        }

        private void UserlistFill(ListView control, List<Record> users, List<Record> ranks)
        {
            control.BeginUpdate();
            control.Items.Clear();
            foreach (Record rank in ranks)
            {
                control.Groups.Add(new ListViewGroup(rank.Name, HorizontalAlignment.Center));
            }
            foreach (Record record in users)
            {
                control.Items.Add(new ListViewItem(record.Name, FindGroup(control, ranks, record.ID)));;
            }
            if (control.Items.Count > 0)
            {
                control.Items[0].Selected = true;
            }
            control.EndUpdate();
        }

        private ListViewGroup FindGroup(ListView control, List<Record> ranks, Int32 id)
        {
            String name = ranks.Find(rank => rank.ID == id).Name;
            foreach (ListViewGroup group in control.Groups)
            {
                if (group.Header.Equals(name))
                {
                    return group;
                }
            }
            return null;
        }

        private void SaveTab(String username)
        {
            if (tcProcessProperties.SelectedTab == tpProcessSecurity)
            {
                SaveSecurityTab(username);
            }
            Database.GetPublicData();
            UserlistFill(lvProcessUsers, Database.Users, Database.Ranks);
        }

        private void SaveSecurityTab(String username)
        {
            SecurityData data = new SecurityData()
            {
                Username = tbProcessUsername.Text,
                Password = (!tbProcessPassword.Text.Equals("<hidden for security>")) ? tbProcessPassword.Text : "",
                Question = tbProcessQuestion.Text,
                Answer = tbProcessAnswer.Text,
                Rank = cbProcessRanks.Text,
                Gender = cbProcessGenders.Text,
                Birthday = dtProcessBirthday.Value
            };
            Database.SaveSecurityData(username, data);
        }
        
        private void SelectUser(String username)
        {
            if (tcProcessProperties.SelectedTab == tpProcessSecurity)
            {
                FillSecurityTab(Database.GetSecurityData(username));
            }
            else if (tcProcessProperties.SelectedTab == tpProcessPrivate)
            {
                FillPrivateTab(Database.GetPrivateData(username));
            }
        }
        
        private void Disconnect()
        {
            Database.Reset();
            ChangeState(ConnectionState.NONE);
        }

        private void ChangeState(ConnectionState state)
        {
            Boolean show = false;
            Boolean enable = false;
            switch (state)
            {
                case ConnectionState.NONE:
                    show = true;
                    enable = true;
                    break;
                case ConnectionState.AUTH:
                    show = true;
                    enable = false;
                    break;
                case ConnectionState.DONE:
                    show = false;
                    enable = true;
                    break;
            }
            pnLogin.Visible = show;
            pnLogin.Enabled = enable;
            btLoginConnect.Text = (enable) ? "CONNECT" : "CONNECTING...";
            pnProcess.Visible = !show;
            miConnect.Enabled = enable;
            miConnect.Text = (show) ? "Connect" : "Disconnect";
            State = state;
            Text = String.Format("AdminPanel [ {0} ]", (show) ? "CyRius Developments" : tbLoginUsername.Text); 
        }

        private Boolean GetEnabled(QueryData data)
        {
            Boolean enabled = false;
            if (data.Permission == PERMISSION.NONE)
            {
                data.Clear();
            }
            else
            {
                enabled = true;
            }
            return enabled;
        }

        private void FillSecurityTab(SecurityData data)
        {
            Boolean enabled = GetEnabled(data);
            foreach (Control control in tpProcessSecurity.Controls)
            {
                if (control.GetType() != typeof(Label))
                {
                    control.Enabled = enabled;
                }
            }
            btSave.Enabled = (data.Permission == PERMISSION.MODIFY);
            tbProcessUsername.Text = data.Username;
            tbProcessPassword.Text = "<hidden for security>";
            tbProcessQuestion.Text = data.Question;
            tbProcessAnswer.Text = data.Answer;
            cbProcessRanks.Text = data.Rank;
            cbProcessGenders.Text = data.Gender;
            dtProcessBirthday.Value = data.Birthday;
        }

        private void FillPrivateTab(PrivateData data)
        {
            Boolean enabled = GetEnabled(data);
            foreach (Control control in tpProcessSecurity.Controls)
            {
                if (control.GetType() != typeof(Label))
                {
                    control.Enabled = enabled;
                }
            }
            btSave.Enabled = (data.Permission == PERMISSION.MODIFY);
            pbPrivateAvatar.Image = (data.Avatar.Image != null) ? data.Avatar.Image : pbPrivateAvatar.InitialImage;
            lvPrivateFriends.BeginUpdate();
            lvPrivateFriends.Items.Clear();
            foreach (Record friend in data.Friends)
            {
                lvPrivateFriends.Items.Add(new ListViewItem(friend.Name, Database.GetRelation(friend.ID)));
            }
            lvPrivateFriends.EndUpdate();
        }

        private void reportButton_Click(object sender, EventArgs e)
        {
            Database.GetReport(rankCheckBox.Checked, genderCheckBox.Checked, stateCheckBox.Checked, banCheckBox.Checked, silenceCheckBox.Checked);
        }

        private void cbProcessRanks_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lvProcessUsers.SelectedItems.Count > 0)
            {
                if (!Database.IsValidRank(lvProcessUsers.SelectedItems[0].Text, cbProcessRanks.Text))
                {
                    cbProcessRanks.SelectedItem = cbProcessRanks.Items[cbProcessRanks.Items.Count - 1];
                }
            }
        }
    }
}
